package com.ytjj.qmyx.supplychain.service;

import com.ytjj.qmyx.supplychain.common.api.CommonResult;
import com.ytjj.qmyx.supplychain.common.constants.RedisKeyUtils;
import com.ytjj.qmyx.supplychain.common.enums.StockFrozenRecordStatusEnums;
import com.ytjj.qmyx.supplychain.common.model.request.ProductStockFrozenRequest;
import com.ytjj.qmyx.supplychain.mapper.BankerProductSpecMapper;
import com.ytjj.qmyx.supplychain.mapper.ProductMapper;
import com.ytjj.qmyx.supplychain.mapper.ProductSpecMapper;
import com.ytjj.qmyx.supplychain.mapper.StockFrozenRecordMapper;
import com.ytjj.qmyx.supplychain.mapper.entity.YxBankerProductSpec;
import com.ytjj.qmyx.supplychain.mapper.entity.YxProduct;
import com.ytjj.qmyx.supplychain.mapper.entity.YxProductSpec;
import com.ytjj.qmyx.supplychain.mapper.entity.YxStockFrozenRecord;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class StockFrozenRecordService {
    @Resource
    private StockFrozenRecordMapper stockFrozenRecordMapper;
    @Resource
    private OrderService orderService;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ProductMapper productMapper;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductSpecService productSpecService;
    @Resource
    private ProductSpecMapper productSpecMapper;
    @Resource
    private BankerProductSpecMapper bankerProductSpecMapper;
    @Value("${product.lock.timer:3}")
    private Integer lockTime;

    /**
     * 新增库存冻结
     * @param request
     * @return
     */
    public CommonResult insert(ProductStockFrozenRequest request) {
        YxStockFrozenRecord record = YxStockFrozenRecord.builder()
                .productId(request.getProductId())
                .productSpecId(request.getProductSpecId())
                .productNum(request.getNum())
                .orderNo(request.getChildOrderNo())
                .createTime(new Date())
                .status(StockFrozenRecordStatusEnums.FROZEN_ING.getStatus())
                .shopId(request.getShopId())
                .build();
        int result = stockFrozenRecordMapper.insert(record);
        return result > 0 ? CommonResult.success() : CommonResult.failed("冻结失败");
    }

    /**
     * 更新库存冻结状态(调用这个方法后 还需要调用下面的subAndAddStock方法)
     * @param orderNo 订单编号
     * @param status 更新状态值 2-已扣库存 3-退还库存 4-冻结作废(超时未支付或取消支付)
     * @return
     */
    public boolean updateStatusByOrderNo(String orderNo, Integer status) {
        log.info("===update stock frozen status==={}, {}", orderNo, status);
        Example example = new Example(YxStockFrozenRecord.class);
        example.createCriteria().andEqualTo("orderNo", orderNo);
        List<YxStockFrozenRecord> recordList = stockFrozenRecordMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(recordList)) {
            log.error("===not found wait update record==={}", orderNo);
            return false;
        }
        YxStockFrozenRecord record = recordList.get(0);
        if (!record.getStatus().equals(StockFrozenRecordStatusEnums.FROZEN_ING.getStatus())) {
            log.warn("===wait update record status is err==={}, {}", orderNo, record.getStatus());
            return false;
        }
//        record.setStatus(status);
//        if (StockFrozenRecordStatusEnums.FROZEN_END.getStatus().equals(status)) {
//            record.setBuckleTime(new Date());
//        }
        if (StockFrozenRecordStatusEnums.FROZEN_REBACK.getStatus().equals(status)) {
            record.setReturnTime(new Date());
        }
        if (StockFrozenRecordStatusEnums.FROZEN_OBSOLETE.getStatus().equals(status)) {
            record.setObsoleteTime(new Date());
            //把订单状态修改为已关闭
            orderService.updateOrderStatus(orderNo, status);
        }
        int result = stockFrozenRecordMapper.updateByPrimaryKeySelective(record);
        return result > 0 ? true : false;
    }

    /**
     * 扣减或退还库存
     * @param orderNo 子订单号
     * @param num 商品数量
     * @param type sub-扣减 add-退还
     * @return
     */
    public boolean subAndAddStock(String orderNo, Integer num,Integer isZeroProduct, String type) {
        RLock lock = redissonClient.getLock(RedisKeyUtils.product_stock_lock + orderNo);
        boolean b = false;
        try {
            //尝试加锁，最多等待lockTime秒，上锁以后lockTime秒自动解锁
            b = lock.tryLock(lockTime, lockTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            lock.unlock();
        }
        if (!b) {
            log.warn("===update product stock is fail by get lock is fail==={}", orderNo);
            return false;
        }
        log.info("===sub or add product stock==={}, {}, {}, {}", orderNo, num, type, isZeroProduct);
        Example example = new Example(YxStockFrozenRecord.class);
        if ("sub".equals(type)){
            example.createCriteria().andEqualTo("orderNo", orderNo).andEqualTo("status",1);
        }else {
            example.createCriteria().andEqualTo("orderNo", orderNo);
        }
        List<YxStockFrozenRecord> list = stockFrozenRecordMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            log.warn("===not found order by sub or add product stock==={}", orderNo);
            return false;
        }
//        YxStockFrozenRecord record = list.get(0);

        list.stream().forEach(record ->{
            log.info("========库存冻结的信息========{}",record);
            Example productExample = new Example(YxProduct.class);
            productExample.createCriteria().andEqualTo("bankerProductId",record.getProductId());
            productExample.setOrderByClause("id desc limit 1");
            YxProduct yxProduct = productMapper.selectOneByExample(productExample);
            boolean product_result = productService.updateProductStock(yxProduct.getId(),num, type,isZeroProduct);
            boolean product_spec_result = productSpecService.updateProductSpecStock(record.getProductSpecId(),num, type);
            log.info("======sub or add product stock result==={}, {}", product_result, product_spec_result);

            if ("sub".equals(type)) {
                record.setStatus(StockFrozenRecordStatusEnums.FROZEN_END.getStatus());
                record.setBuckleTime(new Date());
                int result = stockFrozenRecordMapper.updateByPrimaryKeySelective(record);
            }
        });
        if (null != lock) {
            lock.unlock();
        }
        return true;
    }

    /**
     * 转单后扣减或退还库存
     * @param productId 商品id
     * @param productSpecId 商品规格id
     * @param num 加减数量
     * @param type sub-扣减 add-退还
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean subAndAddStockForTransfer(Integer productId, Integer productSpecId, Integer num, String type) {
        log.info("===开始修改库存==={}, {}, {}", productId, num, type);
        boolean result = false;
        try {
            YxProduct product = productMapper.selectByPrimaryKey(productId);
            YxProductSpec spec = productSpecMapper.selectByPrimaryKey(productSpecId);
            YxBankerProductSpec yxBankerProductSpec = bankerProductSpecMapper.selectByPrimaryKey(spec.getSupplyId());
            //更新商品库存
            productMapper.updateProductStockById(product.getId(), type, num);
            productSpecMapper.updateSpecStockById(spec.getId(),num,type);
            bankerProductSpecMapper.updateBankerProductSpecStockById(yxBankerProductSpec.getId(),num,type);
            result = true;
        } catch (Exception e) {
            log.error("=====更新库存失败=====商品id：{}, 数量：{}, 类型：{}",productId, num, type);
            result = false;
        }
        return result;
    }
}
